use core::marker::PhantomData;
use frame_support::pallet_prelude::{ConstU32, Get};
use precompile_utils::{prelude::*, EvmResult};
use sp_core::{H160, U256};
struct BatchPrecompile<Runtime>(PhantomData<Runtime>);
type GetCallDataLimit = ConstU32<42>;
type GetArrayLimit = ConstU32<42>;
impl<Runtime> BatchPrecompile<Runtime>
where
	Runtime: Get<u32>,
{
	fn pre_check(handle: &mut impl PrecompileHandle) -> EvmResult {
		::core::panicking::panic_fmt(format_args!(
			"not yet implemented: {0}",
			format_args!("pre_check")
		))
	}
	fn batch_some(
		handle: &mut impl PrecompileHandle,
		to: BoundedVec<Address, GetArrayLimit>,
		value: BoundedVec<U256, GetArrayLimit>,
		call_data: BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
		gas_limit: BoundedVec<u64, GetArrayLimit>,
	) -> EvmResult {
		::core::panicking::panic_fmt(format_args!(
			"not yet implemented: {0}",
			format_args!("batch_some")
		))
	}
	fn batch_some_until_failure(
		handle: &mut impl PrecompileHandle,
		to: BoundedVec<Address, GetArrayLimit>,
		value: BoundedVec<U256, GetArrayLimit>,
		call_data: BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
		gas_limit: BoundedVec<u64, GetArrayLimit>,
	) -> EvmResult {
		::core::panicking::panic_fmt(format_args!(
			"not yet implemented: {0}",
			format_args!("batch_some_until_failure")
		))
	}
	fn batch_all(
		handle: &mut impl PrecompileHandle,
		to: BoundedVec<Address, GetArrayLimit>,
		value: BoundedVec<U256, GetArrayLimit>,
		call_data: BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
		gas_limit: BoundedVec<u64, GetArrayLimit>,
	) -> EvmResult {
		::core::panicking::panic_fmt(format_args!(
			"not yet implemented: {0}",
			format_args!("batch_all")
		))
	}
	fn fallback(handle: &mut impl PrecompileHandle) -> EvmResult {
		::core::panicking::panic_fmt(format_args!(
			"not yet implemented: {0}",
			format_args!("fallback")
		))
	}
}
#[allow(non_camel_case_types)]
pub enum BatchPrecompileCall<Runtime>
where
	Runtime: Get<u32>,
{
	batch_all {
		to: BoundedVec<Address, GetArrayLimit>,
		value: BoundedVec<U256, GetArrayLimit>,
		call_data: BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
		gas_limit: BoundedVec<u64, GetArrayLimit>,
	},
	batch_some {
		to: BoundedVec<Address, GetArrayLimit>,
		value: BoundedVec<U256, GetArrayLimit>,
		call_data: BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
		gas_limit: BoundedVec<u64, GetArrayLimit>,
	},
	batch_some_until_failure {
		to: BoundedVec<Address, GetArrayLimit>,
		value: BoundedVec<U256, GetArrayLimit>,
		call_data: BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
		gas_limit: BoundedVec<u64, GetArrayLimit>,
	},
	fallback {},
	#[doc(hidden)]
	__phantom(
		::core::marker::PhantomData<(Runtime)>,
		::core::convert::Infallible,
	),
}
impl<Runtime> BatchPrecompileCall<Runtime>
where
	Runtime: Get<u32>,
{
	pub fn parse_call_data(
		handle: &mut impl PrecompileHandle,
	) -> ::precompile_utils::EvmResult<Self> {
		use precompile_utils::solidity::revert::RevertReason;
		let input = handle.input();
		let selector = input.get(0..4).map(|s| {
			let mut buffer = [0u8; 4];
			buffer.copy_from_slice(s);
			u32::from_be_bytes(buffer)
		});
		match selector {
			Some(2044677020u32) => Self::_parse_batch_some(handle),
			Some(2531431096u32) => Self::_parse_batch_all(handle),
			Some(3473183175u32) => Self::_parse_batch_some_until_failure(handle),
			_ => Self::_parse_fallback(handle),
		}
	}
	fn _parse_batch_all(handle: &mut impl PrecompileHandle) -> ::precompile_utils::EvmResult<Self> {
		use precompile_utils::{
			evm::handle::PrecompileHandleExt,
			solidity::{modifier::FunctionModifier, revert::InjectBacktrace},
		};
		handle.check_function_modifier(FunctionModifier::NonPayable)?;
		let mut input = handle.read_after_selector()?;
		input.expect_arguments(4usize)?;
		Ok(Self::batch_all {
			to: input.read().in_field("to")?,
			value: input.read().in_field("value")?,
			call_data: input.read().in_field("callData")?,
			gas_limit: input.read().in_field("gasLimit")?,
		})
	}
	fn _parse_batch_some(
		handle: &mut impl PrecompileHandle,
	) -> ::precompile_utils::EvmResult<Self> {
		use precompile_utils::{
			evm::handle::PrecompileHandleExt,
			solidity::{modifier::FunctionModifier, revert::InjectBacktrace},
		};
		handle.check_function_modifier(FunctionModifier::NonPayable)?;
		let mut input = handle.read_after_selector()?;
		input.expect_arguments(4usize)?;
		Ok(Self::batch_some {
			to: input.read().in_field("to")?,
			value: input.read().in_field("value")?,
			call_data: input.read().in_field("callData")?,
			gas_limit: input.read().in_field("gasLimit")?,
		})
	}
	fn _parse_batch_some_until_failure(
		handle: &mut impl PrecompileHandle,
	) -> ::precompile_utils::EvmResult<Self> {
		use precompile_utils::{
			evm::handle::PrecompileHandleExt,
			solidity::{modifier::FunctionModifier, revert::InjectBacktrace},
		};
		handle.check_function_modifier(FunctionModifier::NonPayable)?;
		let mut input = handle.read_after_selector()?;
		input.expect_arguments(4usize)?;
		Ok(Self::batch_some_until_failure {
			to: input.read().in_field("to")?,
			value: input.read().in_field("value")?,
			call_data: input.read().in_field("callData")?,
			gas_limit: input.read().in_field("gasLimit")?,
		})
	}
	fn _parse_fallback(handle: &mut impl PrecompileHandle) -> ::precompile_utils::EvmResult<Self> {
		use precompile_utils::{
			evm::handle::PrecompileHandleExt,
			solidity::{modifier::FunctionModifier, revert::InjectBacktrace},
		};
		handle.check_function_modifier(FunctionModifier::NonPayable)?;
		Ok(Self::fallback {})
	}
	pub fn execute(
		self,
		handle: &mut impl PrecompileHandle,
	) -> ::precompile_utils::EvmResult<::fp_evm::PrecompileOutput> {
		use fp_evm::{ExitSucceed, PrecompileOutput};
		use precompile_utils::solidity::codec::Writer;
		let output = match self {
			Self::batch_all {
				to,
				value,
				call_data,
				gas_limit,
			} => {
				let output =
					<BatchPrecompile<Runtime>>::batch_all(handle, to, value, call_data, gas_limit);
				::precompile_utils::solidity::encode_return_value(output?)
			}
			Self::batch_some {
				to,
				value,
				call_data,
				gas_limit,
			} => {
				let output =
					<BatchPrecompile<Runtime>>::batch_some(handle, to, value, call_data, gas_limit);
				::precompile_utils::solidity::encode_return_value(output?)
			}
			Self::batch_some_until_failure {
				to,
				value,
				call_data,
				gas_limit,
			} => {
				let output = <BatchPrecompile<Runtime>>::batch_some_until_failure(
					handle, to, value, call_data, gas_limit,
				);
				::precompile_utils::solidity::encode_return_value(output?)
			}
			Self::fallback {} => {
				let output = <BatchPrecompile<Runtime>>::fallback(handle);
				::precompile_utils::solidity::encode_return_value(output?)
			}
			Self::__phantom(_, _) => {
				::core::panicking::panic_fmt(format_args!("__phantom variant should not be used"))
			}
		};
		Ok(PrecompileOutput {
			exit_status: ExitSucceed::Returned,
			output,
		})
	}
	pub fn supports_selector(selector: u32) -> bool {
		match selector {
			2044677020u32 => true,
			2531431096u32 => true,
			3473183175u32 => true,
			_ => false,
		}
	}
	pub fn selectors() -> &'static [u32] {
		&[2044677020u32, 2531431096u32, 3473183175u32]
	}
	pub fn batch_all_selectors() -> &'static [u32] {
		&[2531431096u32]
	}
	pub fn batch_some_selectors() -> &'static [u32] {
		&[2044677020u32]
	}
	pub fn batch_some_until_failure_selectors() -> &'static [u32] {
		&[3473183175u32]
	}
	pub fn fallback_selectors() -> &'static [u32] {
		&[]
	}
	pub fn encode(self) -> ::precompile_utils::__alloc::vec::Vec<u8> {
		use precompile_utils::solidity::codec::Writer;
		match self {
			Self::batch_all {
				to,
				value,
				call_data,
				gas_limit,
			} => Writer::new_with_selector(2531431096u32)
				.write(to)
				.write(value)
				.write(call_data)
				.write(gas_limit)
				.build(),
			Self::batch_some {
				to,
				value,
				call_data,
				gas_limit,
			} => Writer::new_with_selector(2044677020u32)
				.write(to)
				.write(value)
				.write(call_data)
				.write(gas_limit)
				.build(),
			Self::batch_some_until_failure {
				to,
				value,
				call_data,
				gas_limit,
			} => Writer::new_with_selector(3473183175u32)
				.write(to)
				.write(value)
				.write(call_data)
				.write(gas_limit)
				.build(),
			Self::fallback {} => Default::default(),
			Self::__phantom(_, _) => {
				::core::panicking::panic_fmt(format_args!("__phantom variant should not be used"))
			}
		}
	}
}
impl<Runtime> From<BatchPrecompileCall<Runtime>> for ::precompile_utils::__alloc::vec::Vec<u8>
where
	Runtime: Get<u32>,
{
	fn from(a: BatchPrecompileCall<Runtime>) -> ::precompile_utils::__alloc::vec::Vec<u8> {
		a.encode()
	}
}
impl<Runtime> ::fp_evm::Precompile for BatchPrecompile<Runtime>
where
	Runtime: Get<u32>,
{
	fn execute(
		handle: &mut impl PrecompileHandle,
	) -> ::precompile_utils::EvmResult<::fp_evm::PrecompileOutput> {
		let _: () = <BatchPrecompile<Runtime>>::pre_check(handle)?;
		<BatchPrecompileCall<Runtime>>::parse_call_data(handle)?.execute(handle)
	}
}
#[allow(non_snake_case)]
pub(crate) fn __BatchPrecompile_test_solidity_signatures_inner() {
	use precompile_utils::solidity::Codec;
	match (
		&"(address[],uint256[],bytes[],uint64[])",
		&<(
			BoundedVec<Address, GetArrayLimit>,
			BoundedVec<U256, GetArrayLimit>,
			BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
			BoundedVec<u64, GetArrayLimit>,
		) as Codec>::signature(),
	) {
		(left_val, right_val) => {
			if !(*left_val == *right_val) {
				let kind = ::core::panicking::AssertKind::Eq;
				::core::panicking::assert_failed( kind, &*left_val, &*right_val, ::core::option::Option::Some( format_args!( "{0} function signature doesn\'t match (left: attribute, right: computed from Rust types)", "batch_all" ), ), );
			}
		}
	};
	match (
		&"(address[],uint256[],bytes[],uint64[])",
		&<(
			BoundedVec<Address, GetArrayLimit>,
			BoundedVec<U256, GetArrayLimit>,
			BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
			BoundedVec<u64, GetArrayLimit>,
		) as Codec>::signature(),
	) {
		(left_val, right_val) => {
			if !(*left_val == *right_val) {
				let kind = ::core::panicking::AssertKind::Eq;
				::core::panicking::assert_failed( kind, &*left_val, &*right_val, ::core::option::Option::Some( format_args!( "{0} function signature doesn\'t match (left: attribute, right: computed from Rust types)", "batch_some" ), ), );
			}
		}
	};
	match (
		&"(address[],uint256[],bytes[],uint64[])",
		&<(
			BoundedVec<Address, GetArrayLimit>,
			BoundedVec<U256, GetArrayLimit>,
			BoundedVec<BoundedBytes<GetCallDataLimit>, GetArrayLimit>,
			BoundedVec<u64, GetArrayLimit>,
		) as Codec>::signature(),
	) {
		(left_val, right_val) => {
			if !(*left_val == *right_val) {
				let kind = ::core::panicking::AssertKind::Eq;
				::core::panicking::assert_failed( kind, &*left_val, &*right_val, ::core::option::Option::Some( format_args!( "{0} function signature doesn\'t match (left: attribute, right: computed from Rust types)", "batch_some_until_failure" ), ), );
			}
		}
	};
	match (&"()", &<() as Codec>::signature()) {
		(left_val, right_val) => {
			if !(*left_val == *right_val) {
				let kind = ::core::panicking::AssertKind::Eq;
				::core::panicking::assert_failed( kind, &*left_val, &*right_val, ::core::option::Option::Some( format_args!( "{0} function signature doesn\'t match (left: attribute, right: computed from Rust types)", "fallback" ), ), );
			}
		}
	};
}
